package com.zdp.provider.Command;

import com.netflix.hystrix.HystrixCollapser;
import com.netflix.hystrix.HystrixCommand;
import com.netflix.hystrix.HystrixCommandGroupKey;
import com.netflix.hystrix.HystrixCommandKey;
import com.netflix.hystrix.contrib.javanica.command.BatchHystrixCommand;
import com.zdp.provider.controller.CourseDto;
import com.zdp.provider.service.CourseService;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 类描述:  课程请求合并 相关处理
 * List<CourseDto> : BatchReturnType （批处理返回的类型）
 * CourseDto : ResponseType （返回参数类型）
 * Integer : RequestArgumentType ( 请求参数类型）
 * @author ZhhengDP
 * @since 2021/8/26
 */
public class CourseCommandCollapser extends HystrixCollapser<List<List<CourseDto>>,List<CourseDto>,Integer> {

    private CourseService courseService;
    private Integer teacherId;

    public CourseCommandCollapser(CourseService courseService,Integer teacherId){
        this.courseService = courseService;
        this.teacherId = teacherId;
    }

    /**
     * 获取到要加载的teacherId
     * @return
     */
    @Override
    public Integer getRequestArgument() {
        return this.teacherId;
    }

    /**
     * 实现请求参数的批量封装
     * @param collapsedRequests  被合并的请求的集合
     * @return 批量加载得到的课程
     */
    @Override
    protected HystrixCommand<List<List<CourseDto>>> createCommand(Collection<CollapsedRequest<List<CourseDto>, Integer>> collapsedRequests) {
        List<Integer> teacherIds = new ArrayList<>(collapsedRequests.size());
        teacherIds.addAll(collapsedRequests.stream()
                .map(CollapsedRequest::getArgument)
                .collect(Collectors.toList()));
        return new BatchCommand(this.courseService,teacherIds);
    }

    /**
     * 将批量加载的课程映射到对应的请求中
     * @param batchResponse 批量加载得到的课程
     * @param collapsedRequests 所有被合并的请求
     */
    @Override
    protected void mapResponseToRequests(List<List<CourseDto>> batchResponse,
                                         Collection<CollapsedRequest<List<CourseDto>, Integer>> collapsedRequests) {
        int count = 0;
        for(CollapsedRequest<List<CourseDto>,Integer> request:collapsedRequests){
            request.setResponse(batchResponse.get(count++));
        }
    }

    /**
     * 处理批量请求的Command对象
     */
    private static final class BatchCommand extends HystrixCommand<List<List<CourseDto>>> {
        private CourseService courseService;
        private List<Integer> teacherIds;

        private BatchCommand(CourseService courseService,List<Integer> teacherIds){
            super(Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("UserCommand"))
            .andCommandKey(HystrixCommandKey.Factory.asKey("GetUserForId")));
            this.courseService = courseService;
            this.teacherIds = teacherIds;
        }

        // 批量处理的真正处理逻辑
        @Override
        protected List<List<CourseDto>> run() throws Exception {
            return this.courseService.batchFindCourses(teacherIds);
        }
    }
}
